module.exports = {


  friendlyName: 'Set compliant versions',


  description: 'Sets complaint versions for a single type of critical software and returns that software type\'s new patch progress.',


  inputs: {
    complianceType: {
      type: 'string',
      isIn: [
        'operatingSystem',
        'firefox',
        'microsoftOffice',
        'flash',
        'chrome',
        'safari',
      ],
    },
    compliantVersions: {
      type: 'ref',
      description: 'An array of Ids that will be used to set complaint versions of CriticalInstall or OperatingSystem records'
    }
  },


  exits: {

  },


  fn: async function ({complianceType, compliantVersions}) {


    let newPatchProgress;
    let numberOfComplaintHosts;
    let newCompliantVersions;
    let numberOfHosts = await Host.count();
    let newCompliantInstalls = [];
    // If complainceType is operatingSystem
    if(complianceType === 'operatingSystem') {

      // Clear out existing explicitly marked complaint operating systems
      await OperatingSystem.update({}).set({isCompliant: false});
      newCompliantVersions = await OperatingSystem.update({id: {in: compliantVersions}}).set({isCompliant: true}).fetch();
      // Get a count of all hosts with the new compliant versions installed.
      numberOfComplaintHosts = await Host.count({operatingSystem: {in: compliantVersions}});
      newPatchProgress = Math.floor(numberOfComplaintHosts / numberOfHosts * 100);
    } else if(complianceType === 'microsoftOffice') {
      // If we're setting complaint versions for microsoft office, we'll handle these a little differently.
      // Because microsoft office is a suite of programs that all share a version, if a version is marked as compliant,
      // we'll change all microsoft office installs with the same version and platform as the specified version to be in compliance as well.

      await CriticalInstall.update({softwareType: complianceType}).set({isCompliant: false}); // Clear out existing complaint versions of microsoft office.
      let theseInstalls = await CriticalInstall.find({softwareType: complianceType}).select('host'); // Get the total number of installs
      let hostsWithMicrosoftOfficeInstalled = _.uniq(theseInstalls, 'host');
      // For MS Office installs, we'll update the compliant versions individually, this is so we can update the versions for each operating system individually.
      for(let specifiedVersion of compliantVersions) {
        let specifiedCompliantSoftware = await CriticalInstall.find({softwareType: 'microsoftOffice', fleetApid: specifiedVersion});
        if(specifiedCompliantSoftware.length === 0){
          throw new Error(`Could not set complaint versions of Microsoft Office! No Microsoft Office installs were matching the provided fleetApid were found.`);
        }
        newCompliantVersions = await CriticalInstall.update({
          softwareType: 'microsoftOffice',
          versionName: specifiedCompliantSoftware[0].versionName,
          platform: specifiedCompliantSoftware[0].platform
        })
        .set({isCompliant: true}).fetch();
        newCompliantInstalls = newCompliantInstalls.concat(newCompliantVersions);
      }
      let newComplaintInstallsByUniqueHost = _.uniq(newCompliantInstalls, 'host');
      newPatchProgress = (newComplaintInstallsByUniqueHost.length / hostsWithMicrosoftOfficeInstalled.length * 100);
    } else {
      await CriticalInstall.update({softwareType: complianceType}).set({isCompliant: false});
      let numberOfTheseInstalls = await CriticalInstall.count({softwareType: complianceType});
      newCompliantVersions = await CriticalInstall.update({fleetApid: {in: compliantVersions}}).set({isCompliant: true}).fetch();
      newPatchProgress = Math.floor(newCompliantInstalls.length /numberOfTheseInstalls * 100);
    }


    // All done.
    return newPatchProgress;

  }


};
